#include "stm32f10x.h"                  // Device header


// TIM2 -> APB1 总线上的外设
void Timer_Init(void)
{
	// 开启APB1上的 TIM2 时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	
	// ETR 外部时钟需要使用 A0 引脚的 GPIO 输入, 因此需要 APB2 总下下开启 GPIOA 的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	// 配置 PA0 口 GPIO 配置
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;   // 推荐是浮空输入, 但是这里给上拉输入.
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
	

	// 通过 ETR 引脚的外部时钟模式2配置
	// 第1个参数是使用那个定时器
	// 第2个参数是预分频
	// 第3个参数是外部触发的极性，低电平 或 下降沿有效 
	//                            | 高电平 或 上升沿有效
	// 第4个参数是外部触发滤波器，这个值必须是 0x00 到 0x0F 之间的一个值, 这个滤波很有必要, 否则一次信号触发多次计数器增加的问题.
	TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F);
	// TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_Inverted, 0x0F);
	
	// 配置时基单元
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;        // 这个是外部时钟的时候，消抖采样的频率对内部时钟的分频, 随便配置一个即可。
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;    // 向上计数
	TIM_TimeBaseInitStruct.TIM_Period = 10 - 1;                     // 计数重装值, ARR
	TIM_TimeBaseInitStruct.TIM_Prescaler = 1 - 1;                   // 预分频, PSC, 注意 PSC 和 ARR 都要在 0~65535 之间, 公式: 
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;               // 高级定时器才会使用, 我们不用管
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
	
	// 清除预分频设置的更新中断标志位, 避免上电就进入一次中断.
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);
	
	// 使能更新中断: 开启更新中断到 NVIC 得通路, 第三个参数是 NVIC 前面的中断输出控制
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	
	// NVIC 配置
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                 // 优先级分组
	NVIC_InitTypeDef NVIC_InitStructure; 
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;                 // 定时器2 在 NVIC 里的通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	// 启动定时器
	TIM_Cmd(TIM2, ENABLE);
}

uint16_t Timer_GetCounter(void)
{
	return TIM_GetCounter(TIM2);
}